# -*- coding: utf-8 -*-
"""
len() 函数的专用回调处理器

处理 len 函数调用的不同场景：
1. 对于有 __len__ 方法的类型，优先调用 __len__()
2. 对于没有 __len__ 方法的类型，返回 None，让模板系统使用全局 len 函数的模板
"""

from typing import Optional
from mcpy.ir.expressions.call import IRCall
from mcpy.codegen.core.context import CodeGenContext
from mcpy.codegen.core.emitter import EmitResult


class LenFunctionCallback:
    """len() 函数的回调处理器"""

    def emit(self, node: IRCall, context: CodeGenContext) -> Optional[EmitResult]:
        """生成 len() 调用的代码

        Args:
            node: IRCall 节点
            context: 代码生成上下文

        Returns:
            EmitResult 或 None（如果不处理，让模板系统使用全局 len 函数）
        """
        from mcpy.codegen.core.generator import get_global_generator

        generator = get_global_generator()

        # 确保有参数
        if not node.args or len(node.args) == 0:
            return None

        # 获取第一个参数
        arg = node.args[0]

        # 获取参数的推断类型
        arg_type_info = arg.get_extension_param("inferred_type")
        if not arg_type_info or not context.current_node:
            # 无法获取类型信息，返回 None 让模板系统处理
            return None

        # 获取参数的 C++ 类型
        from mcpy.type_system import get_cpp_type
        from mcpy.symbol_meta import TypeKind

        arg_cpp_type = get_cpp_type(arg_type_info, arg)
        if not arg_cpp_type:
            return None

        # 特殊处理：Any 类型（mc::variant）
        # 对于 Any 类型，mc::variant 有 size() 方法可以直接使用
        if arg_type_info.kind == TypeKind.ANY or arg_cpp_type == "mc::variant":
            # 生成参数代码
            arg_code = generator.generate_expression(
                arg, context, parent_precedence=100
            )
            # 对于 mc::variant，直接使用 size() 方法
            return EmitResult(
                code=f"{arg_code}.size()",
                precedence=2,
            )

        # 查找 __len__ 方法
        method_symbol = context.current_node.lookup_symbol(
            "__len__",
            owner_type=arg_type_info,
            func_args=[],
            template_args=arg_type_info.args if arg_type_info.args else None,
        )

        if method_symbol:
            # 找到了 __len__ 方法，获取匹配的签名
            matching_signature = method_symbol.find_matching_signature([arg_type_info])
            if not matching_signature and method_symbol.signatures:
                matching_signature = method_symbol.signatures[0]

            if matching_signature:
                # 获取模板
                template = matching_signature.emit_template
                if template:
                    # 生成参数代码
                    arg_code = generator.generate_expression(
                        arg, context, parent_precedence=100
                    )
                    # 应用模板生成代码
                    code = template.replace("{self}", arg_code)

                    # 添加必要的包含文件
                    includes = getattr(matching_signature, "includes", [])
                    for include in includes:
                        context.require_include(include)

                    return EmitResult(code=code, precedence=2)

        # 没有找到 __len__ 方法，返回 None 让模板系统使用全局 len 函数的模板
        return None
